package hns.services;

import hns.Bot;
import hns.Service;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.jibble.pircbot.Colors;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class ClanWarService implements Service {
	private String command = "!cw";
	private ArrayList<ClanWar> cwList = null;
	private String clanwarXMLfile = "clanwars.xml";


	public ClanWarService() {
		Bot.getInstance().addService(command, this);
		try {
			loadCWlist(clanwarXMLfile);
		} catch (Exception e) {
			System.out.println("Could not load XML CW File: "+e.getMessage());
			e.printStackTrace();
		}
	}

	@Override
	public String getCommandName() {
		return command;
	}

	@Override
	public void onMessage(String channel, String sender, String login,
			String hostname, String message) {
		boolean hasNext = false;
		String[] params = message.split(" ");

		if (params.length < 2) {
			sendSyntax(channel);
			return;
		}

		switch (params[1]) {
		case "new":
			if(params.length < 4) { sendSyntax(channel); break;}
			if(params[2] == null || params[3] == null){ sendSyntax(channel); break;}
			try{
				ClanWar cw = new ClanWar();
				Date d = DateFormat.getDateInstance().parse(params[2]);
				cw.setDate(d);
				cw.setOpponent(params[3]);
				cwList.add(cw);
				Bot.getInstance().sendMessage(channel, "Match against "+cw.getOpponent()+" on the "+cw.getDate()+ " added!");
			}catch(ParseException e){
				sendSyntax(channel);
			}
			break;
		case "status":
			for(ClanWar cw : cwList){
				if(cw.date.after(new Date())){
					StringBuilder players = new StringBuilder();
					int teamsize = cw.getPlayers().size();
					players.append(" || Team ("+teamsize+"/6): ");
					for(String p : cw.getPlayers()){
						players.append(" "+p+" ");
					}
					if(teamsize < 6){
						for(int i = teamsize; i < 6; i++){
							players.append(" [Open] ");
						}
					}
					Bot.getInstance().sendMessage(channel, "Upcoming " +cw.getTypeCW()+ " vs: "+cw.getOpponent()+" at "+cw.getDate()+players.toString());
					hasNext = true;
				}
			}
			if(!hasNext)
				Bot.getInstance().sendMessage(channel, "No upcoming matches!");
			break;
		case "reload":
			cwList.clear();
			try {
				loadCWlist(clanwarXMLfile);
				Bot.getInstance().sendMessage(channel, "Succesfully reloaded CW List");
			} catch (Exception e) {
				Bot.getInstance().sendMessage(channel, "Could not load XML CW File: "+e.getMessage());
				e.printStackTrace();
			}
			break;
		default:
			sendSyntax(channel);
		}
	}

	@Override
	public void onJoin(String channel, String sender, String login,
			String hostname) {
		// TODO Auto-generated method stub

	}
	
	/**
	 * Not yet implemented
	 * @param clanwarsXMLfile 
	 * @throws Exception 
	 */
	private void loadCWlist(String clanwarsXMLfile) throws Exception{
		if(cwList == null)
			cwList = new ArrayList<ClanWar>();
		
		File xmlFile = new File(clanwarsXMLfile);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(xmlFile);
		doc.getDocumentElement().normalize();
		
		NodeList cws = doc.getElementsByTagName("cw");
		for(int i = 0; i < cws.getLength(); i++){
			ClanWar CW = new ClanWar();
			Node cwN = cws.item(i);
			System.out.println("Found new CW");
			
			// For each CW node
			if(cwN.getNodeType() ==  Node.ELEMENT_NODE){
				Element cwE = (Element) cwN;
				CW.setDate(new Date(Long.parseLong(cwE.getAttribute("time")) * 1000)); // Java's Date constructor takes milliseconds.
				CW.setTypeCW(cwE.getAttribute("type"));
				System.out.println("Added date and type: "+CW.getDate().toString()+ " || "+CW.getTypeCW());
				
				// For opponent node (Only got 1)
				Node opponentN = cwE.getElementsByTagName("opponent").item(0);
				Element opponentE = (Element) opponentN;
				CW.setOpponent(opponentE.getAttribute("name"));
				CW.setOpponentCountry(opponentE.getAttribute("country"));
				System.out.println("Added opponent and country: "+CW.getOpponent()+", from "+CW.getOpponentCountry());
				
				// For each map
				Node mapsN = cwE.getElementsByTagName("maps").item(0);
				Element mapsE = (Element) mapsN;
				NodeList mapList = mapsE.getElementsByTagName("map");
				for(int j = 0; j < mapList.getLength(); j++){
					Element mapE = (Element) ((Node)mapList.item(j));
					switch(mapE.getAttribute("name")){
					case "ns2_veil":
						CW.addMap(Maps.ns2_veil);
						System.out.println("Added map: ns2_veil");
						break;
					case "ns2_tram":
						CW.addMap(Maps.ns2_tram);
						System.out.println("Added map: ns2_tram");
						break;
					case "ns2_summit":
						CW.addMap(Maps.ns2_summit);
						System.out.println("Added map: ns2_summit");
						break;
					}
				}
				
				// For each player
				Node playersN = cwE.getElementsByTagName("players").item(0);
				Element playersE = (Element) playersN;
				NodeList playerList = playersE.getElementsByTagName("player");
				for(int j = 0; j < playerList.getLength(); j++){
					Element playerE = (Element) playerList.item(j);
					CW.addPlayer(playerE.getAttribute("name"));
					System.out.println("Added player: "+playerE.getAttribute("name"));
				}
				
				// Add the processed CW to the CWlist
				cwList.add(CW);
				System.out.println("Completed processing, added the CW to the CW List");
			}else{
				throw new Exception("node was not an Element node!");
			}
		}
	}
	
	/**
	 * Not yet implemented
	 */
	private void saveCWlist(){

	}

	private void sendSyntax(String target) {
		String message = "CW System syntax: !cw (status|reload|signup [nick]|remove [nick]|new [dd-mm-yyyy] [opponent])";
		Bot.getInstance().sendMessage(target, message);
	}
	
	public enum Maps{
		ns2_veil, ns2_tram, ns2_summit
	}
	
	private class ClanWar {
		private ArrayList<String> players;
		private Date date = null;
		private String opponent;
		private String opponentCountry;
		private ArrayList<Maps> maps;
		
		ClanWar(){
			players = new ArrayList<String>();
			maps = new ArrayList<Maps>();
		}
		
		public ArrayList<String> getPlayers() {
			return players;
		}
		
		public void addPlayer(String p){
			players.add(p);
		}
		
		public ArrayList<Maps> getMaps() {
			return maps;
		}
		
		public void addMap(Maps m){
			maps.add(m);
		}

		public String getOpponentCountry() {
			return opponentCountry;
		}

		public void setOpponentCountry(String opponentCountry) {
			this.opponentCountry = opponentCountry;
		}

		private String typeCW;
		public String getTypeCW() {
			return typeCW;
		}

		public void setTypeCW(String typeCW) {
			this.typeCW = typeCW;
		}
		
		public void setDate(Date d){
			date = d;
		}
		
		public String getDate(){
			return DateFormat.getInstance().format(date);
		}
		
		public String getOpponent(){
			return opponent;
		}
		
		public void setOpponent(String o){
			opponent = o;
		}
	}
}
